package com.baitiaojun.elasticsearch.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baitiaojun.api.domain.video.Video;
import com.baitiaojun.api.exception.ConditionException;
import com.baitiaojun.api.util.ConstantUtil;
import com.baitiaojun.elasticsearch.repository.VideoRepository;
import com.baitiaojun.elasticsearch.service.VideoService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.adjacency.AdjacencyMatrixAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.cardinality.CardinalityAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @类名 VideoServiceImpl
 * @描述 TODO
 * @作者 白条君
 * @创建日期 2022/12/20 23:39
 * @版本 1.0
 */
@Service
public class VideoServiceImpl implements VideoService {

    @Autowired
    private VideoRepository videoRepository;

    @Autowired
    private RestHighLevelClient client;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public void save(Video video) throws ConditionException {
        Video res = videoRepository.save(video);
        if (ObjectUtils.isEmpty(res)) {
            throw new ConditionException();
        }
    }

    @Override
    public List<Video> getPageHomeVideoList(Long lastId, Integer pageSize, String... area) throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //search_after方式分页查看
        searchSourceBuilder.size(pageSize);
        searchSourceBuilder.sort(SortBuilders.fieldSort("id").order(SortOrder.ASC));
        if (ObjectUtils.notEqual(lastId, 0L)) {
            Object[] values =  {lastId};
            searchSourceBuilder.searchAfter(values);
        }
        //查找条件
        if (ObjectUtils.isNotEmpty(area) && area.length > 0) {
            searchSourceBuilder.query(QueryBuilders.termQuery("area", area[0]));
        }
        //排出字段
        String[] excludes = {"url", "userId", "type", "createtime", "description", "tags", "area"};
        searchSourceBuilder.fetchSource(null, excludes);
        //查找
        searchRequest.indices("video");
        searchRequest.source(searchSourceBuilder);
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
        //把结果集转化为list集合
        List<Map<String, Object>> list = Arrays.stream(search.getHits().getHits()).map(SearchHit::getSourceAsMap).collect(Collectors.toList());
        return JSONObject.parseArray(JSONObject.toJSONString(list), Video.class);
    }

    @Override
    public void updateVideo(List<Long> videoIds) throws IOException {
        UpdateRequest updateRequest = new UpdateRequest();
        updateRequest.index("video");
        updateRequest.type("_doc");
        Object viewCount;
        Object commentCount;
        for (Long videoId : videoIds) {
            ValueOperations<String, Object> operations = redisTemplate.opsForValue();
            viewCount = operations.get(ConstantUtil.VIEW_COUNT + videoId);
            commentCount = operations.get(ConstantUtil.COMMENT_COUNT + videoId);
            //更新浏览次数
            if (ObjectUtils.isNotEmpty(viewCount) && (int) viewCount % 50 == 0) {
                updateRequest.id(String.valueOf(videoId));
                updateRequest.doc(XContentFactory.jsonBuilder().startObject()
                        .field("viewCount", (int) viewCount).endObject());
                client.update(updateRequest, RequestOptions.DEFAULT);
            }
            //更新评论条数
            if (ObjectUtils.isNotEmpty(commentCount) && (int) commentCount % 20 == 0) {
                updateRequest.id(String.valueOf(videoId));
                updateRequest.doc(XContentFactory.jsonBuilder().startObject()
                        .field("commentCount", (int) commentCount).endObject());
                client.update(updateRequest, RequestOptions.DEFAULT);
            }
        }
    }

    @Override
    public void removeVideo(Long id) {
        videoRepository.deleteById(id);
    }
}